前一篇文章示範使用 Semantic Kernel 內建的模型連接服務串接 OpenAI 的 DALL-E 模型,快速做成一個以文生圖的應用,然而有些時候這些內建的服務無法滿足需求時,又該怎麼辦?
以前一篇的範例為例,內建的服務所提供的參數有限,它並沒有提供 quality(成像品質)、style(成像風格)、n(成像數量) 等這些DALL-E 模型 API 參數。這時候我們就可以利用 Plugins 自已實現 API 呼叫來取代原本內建的模型連接服務。
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(modelId: Config.openai_modelId, apiKey: Config.openai_apiKey)
.Build();
public class OpenAIPlugin
{
private static readonly HttpClient client = new HttpClient();
[KernelFunction, Description("Given a prompt will generate a new image.")]
public string GenImage([Description("user prompt for generate image")] string prompt)
{
var apiKey = Config.openai_apiKey; // 請替換為您的 API 金鑰
var requestBody = new
{
model = "dall-e-3",
prompt = prompt,
n = 1, //number of images to generate,dall-e-3, only n=1 is supported
quality = "hd", //standard or hd
style = "vivid", //vivid or natural
size = "1024x1024"
};
var content = new StringContent(
JsonConvert.SerializeObject(requestBody),
Encoding.UTF8, "application/json"
);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var response = client.PostAsync("https://api.openai.com/v1/images/generations", content).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
var responseBody = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var jsonResponse = JObject.Parse(responseBody);
var imageUrl = jsonResponse["data"][0]["url"].ToString();
return imageUrl;
}
}
kernel.Plugins.AddFromType<OpenAIPlugin>();
OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
var imageDescription ="一鄉二里共三夫子,不識四書五經六義,竟敢教七八九子,十分大膽";
Console.WriteLine("Image URL: " + await kernel.InvokePromptAsync(imageDescription, new(settings)));
var imageDescription =
"""
請根據以下描述,產生圖片,你只需回覆圖片的網址,不要有其它任何的解釋。
### 描述
一鄉二里共三夫子,不識四書五經六義,竟敢教七八九子,十分大膽
""";
Console.WriteLine("Image URL: " + await kernel.InvokePromptAsync(imageDescription, new(settings)));
當 Semantic Kernel 裡所提供的內建服務或 Plugin 無法滿足需求時,做為一個高度抽象化的 Semantic Kernel 是有足夠的方式可以支援客製化處理的。以本次的情境來說,透過撰寫 Plugin 就能有效的解決。也許讀者會產生另一個疑問那一開始就直接呼叫 OpenAI REST API ,何必用 Semantic Kernel 再寫 Plugin 呢 ? 其實在本系列第一篇就採討了這個問題,在簡單的LLMs應用當然 REST API 就能實現,但如果想進一步使用包含對話記錄、RAG 等,這時候有個框架可以套用會相對方便很多,更細的內容可以參考本系列第一篇文章。